/* ******************************************** */
/* * The GapFillerBadKiller                   * */
/* * Authors: André Bannwart Perina           * */
/* *          Antonio Canabrava Fraideinberze * */
/* *          Willian Felipe Lopes da Silva   * */
/* ******************************************** */

#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

/**
 * Fill gaps left by robot.sh and fix bad files
 */
int main(int argc, char *argv[]) {
	int i, n, val, deltaSize, badCounter = 0, goodCounter = 0;
	char *fileName, *robotExec, *rmExec, *generateExec;
	bool runAgain, noAction;
	FILE *ipf;
	FILE *opf;
	clock_t init = clock();

	if(5 != argc) {
		fprintf(stderr, "Usage: %s n filesPrefix deltaSize noAction\n Where: No action is made (verbose only) if noAction != 0.\n", argv[0]);
		return EXIT_FAILURE;
	}

	/* Number of files */
	n = atoi(argv[1]);
	/* Number of genes */
	deltaSize = atoi(argv[3]);
	/* noAction flag: if it's true, nothing is made, the program only report the state of each file */
	noAction = atoi(argv[4])? true : false;
	/* fileName string, used to execute external applications */
	fileName = malloc((strlen(argv[2]) + ((int) log10(n)) + 2) * sizeof(char));
	/* robot.sh execution string */
	robotExec = malloc((21 + (int) log10(n))*sizeof(char));
	/* rm execution string */
	rmExec = malloc((strlen(argv[2]) + ((int) log10(n)) + 6) * sizeof(char));
	/* generate execution string */
	generateExec = malloc((((int) log10(deltaSize)) + ((int) log10(n)) + 20)*sizeof(char));

	do {
		/* Reset runAgain flag */
		runAgain = false;

		/* Run for all files */
		for(i = 0; i < n; i++) {
			/* Mount fileName */
			sprintf(fileName, "%s%d", argv[2], i);

			/* Fitness file is missing, rerun robot.sh for this case */
			if(NULL == (ipf = fopen(fileName, "r"))) {
				/* Only print message */
				if(noAction)
					printf("[%lf] File %s is missing.\n", ((double) (clock() - init)) / CLOCKS_PER_SEC, fileName);
				/* Run robot.sh */
				else {
					printf("[%lf] File %s is missing, filling gap...", ((double) (clock() - init)) / CLOCKS_PER_SEC, fileName);
					sprintf(robotExec, "./robot.sh 6600 1 %d\n", i);
					system(robotExec);
					printf("Done.\n");

					/* This fitness file must be analysed again for bad fitness on next iteration */
					runAgain = true;
				}
			}
			/* Fitness file exists */
			else {
				/* Read first fitness value */
				fscanf(ipf, "%d", &val);
				fclose(ipf);

				/* Bad file (robot crashed or deadlock was reached), recreate delta file */
				if(-1 == val) {
					/* Only print message */
					if(noAction)
						printf("[%lf] File %s is present but bad.\n", ((double) (clock() - init)) / CLOCKS_PER_SEC, fileName, fileName);
					/* Run rm and generate to recreate delta file */
					else {
						printf("[%lf] File %s is present but bad, remaking delta file and removing %s...", ((double) (clock() - init)) / CLOCKS_PER_SEC, fileName, fileName);
						sprintf(rmExec, "rm %s\n", fileName);
						system(rmExec);
						sprintf(generateExec, "./bin/generate %d 1 %d\n", deltaSize, i);
						system(generateExec);
						printf("Done.\n");

						/* Sleep 1 second to make sure that seed will be different for next generate */
						sleep(1);

						/* Count bad file (only if it's first iteration) */
						if(badCounter >= 0)
							badCounter++;

						/* This delta file must be ran again for creating fitness file on next iteration */
						runAgain = true;
					}
				}
				/* Good file */
				else {
					printf("[%lf] File %s is present and good.\n", ((double) (clock() - init)) / CLOCKS_PER_SEC, fileName);

					/* Count good file (only if it's first iteration) */
					if(goodCounter >= 0)
						goodCounter++;
				}
			}
		}

		/* runAgain flag is true. Run another batch */
		if(runAgain)
			printf("[%lf] There are still possible gaps or bad files, running loop again.\n", ((double) (clock() - init)) / CLOCKS_PER_SEC);

		/* Make counters negative. This will maintain its values until the end of execution */
		if(goodCounter >= 0)
			goodCounter *= -1;
		if(badCounter >= 0)
			badCounter *= -1;

	} 	while(runAgain);

	printf("[%lf] GapFillerBadKiller is done. There was %d good files and %d bad files initially.\n", ((double) (clock() - init)) / CLOCKS_PER_SEC, -goodCounter, -badCounter);

	opf = fopen("stats/stats", "w");
	fprintf(opf, "%d %d", -goodCounter, -badCounter);
	fclose(opf);

	/* Free everything */
	free(fileName);
	free(robotExec);
	free(rmExec);
	free(generateExec);

	return EXIT_SUCCESS;
}